﻿// Inner Fire 游戏引擎库
// UI Mesh管理器
//
// Copyright (c) 2024 by 尔西大帝. All rights reserved.
//
// 用于管理所有的UI MESH
//
// Author: 尔西大帝
// Email: 2670613871@qq.com
// Created: 2024-12-24

#include "ui_mesh_manager.h"

namespace ifire::dx {

///////////////////////////////////////////////////////////////////////////////
// UIMeshManager
///////////////////////////////////////////////////////////////////////////////
UIMeshManager::UIMeshManager(const UIMeshDesc& text_desc,
    const UIMeshDesc& image_desc, const UICanvasDesc& canvas_desc) {
  text_ = std::make_unique<UIMesh>(text_desc);
  image_ = std::make_unique<UIMesh>(image_desc);
  canvas_ = std::make_unique<UICanvas>(canvas_desc);
}

DxText* UIMeshManager::CreateText(
    const DxTextDesc& desc, UIRenderItem* parent) {
  // 创建项目
  auto item = std::make_unique<DxText>(desc);
  // 从数据池中分配一块空间
  item->mPoolIndex = Text()->AllocVertex(desc.Capacity);
  // 设置此项目的数据
  item->SetRefresh();
  item->SetCanvas(canvas_.get());
  item->SetParent(parent);

  // 得到返回项目
  DxText* result_ptr = item.get();
  // 设置到项目中
  text_items_.push_back(std::move(item));

  return result_ptr;
}

DxImage* UIMeshManager::CreateImage(
    const DxImageDesc& desc, UIRenderItem* parent) {
  // 创建项目
  auto item = std::make_unique<DxImage>(desc);
  // 从数据池中分配一块空间
  item->mPoolIndex = Image()->AllocVertex(1);
  // 设置此项目的数据
  item->SetCanvas(canvas_.get());
  item->SetParent(parent);
  item->SetRefresh();

  // 得到返回项目
  DxImage* result_ptr = item.get();
  // 设置到项目中
  image_items_.push_back(std::move(item));

  return result_ptr;
}

DxLayout* UIMeshManager::CreateLayout(
    const DxLayoutDesc& desc, UIRenderItem* parent) {
  auto item = std::make_unique<DxLayout>(desc);
  item->SetCanvas(canvas_.get());
  item->SetParent(parent);

  auto ptr = item.get();
  layouts_.push_back(std::move(item));
  return ptr;
}

void UIMeshManager::UpdateText(UploadBuffer<UIInstancedData>* uploader) {

  // 遍历每个游戏对象，设置他们的信息
  for (auto& e : text_items_) {
    // 得到值
    DxText* item = e.get();

    // 仅当项目已经发生变化时才设置
    if (item->frame_dirty_count > 0) {
      item->Update(ClientSize(), uploader);
      // 其它的帧同样也要更新
      item->frame_dirty_count--;
    }
  }
}

void UIMeshManager::UpdateImage(UploadBuffer<UIInstancedData>* uploader) {
  // 用于更新的项目
  UIInstancedData data{};

  // 遍历每个游戏对象，设置他们的信息
  for (auto& e : image_items_) {
    // 得到值
    DxImage* item = e.get();

    // 仅当项目已经发生变化时才设置
    if (item->frame_dirty_count > 0) {
      // 必须保证索引在Image的范围之内
      assert(item->mPoolIndex < uploader->size());

      // 更新项目
      item->Update(ClientSize(), data);
      // 需要复制到cb_index指针的位置
      uploader->CopyData(item->mPoolIndex, data);
      // 其它的帧同样也要更新
      item->frame_dirty_count--;
    }
  }
}

} // namespace ifire::dx